package com.whcoding.base.project.common;



import cn.hutool.core.text.csv.CsvUtil;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: spring-boot-learning
 * @description:
 * @author: whcoding
 * @create: 2022-02-15 11:28
 **/
public class CSVUtils {

	/**
	 * 日志对象
	 */
	private static final Logger log = LoggerFactory.getLogger(CsvUtil.class);

	/**
	 * io流导出
	 *
	 * @param file     csv文件(路径+文件名)，csv文件不存在会自动创建
	 * @param dataList 数据，字符串用逗号分隔
	 * @return 返回导出是否成功 true成功 false失败
	 */
	public static boolean exportCsv(File file, List<String> dataList) {
		boolean isSucess = false;

		FileOutputStream out = null;
		OutputStreamWriter osw = null;
		BufferedWriter bw = null;
		try {
			out = new FileOutputStream(file);
			//解决FileOutputStream中文乱码问题  解决MS office乱码问题
			osw = new OutputStreamWriter(out, "GBK");
			bw = new BufferedWriter(osw);
			if (dataList != null && !dataList.isEmpty()) {
				for (String data : dataList) {
					bw.append(data).append("\r");
				}
			}
			isSucess = true;
		} catch (Exception e) {
			isSucess = false;
		} finally {
			if (bw != null) {
				try {
					bw.close();
					bw = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (osw != null) {
				try {
					osw.close();
					osw = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (out != null) {
				try {
					out.close();
					out = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return isSucess;
	}

	/**
	 * 导入
	 *
	 * @param file csv文件(路径+文件)
	 * @return 返回List<String>列表
	 */
	public static List<String> importCsv(File file) {
		List<String> dataList = new ArrayList<String>();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			String line = "";
			while ((line = br.readLine()) != null) {
				dataList.add(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
					br = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return dataList;
	}

	/**
	 * apache commons-csv导出
	 * 注意jdk要在1.7及以上使用
	 * map的数据个数要与header的个数相等 并且一一对应，可参照main方法
	 *
	 * @param filePath 文件存储路径
	 * @param list     数据列表
	 * @param header   表头
	 */
	public static void csvWrite(String filePath, List<LinkedHashMap<String, String>> list, String... header) {
		try {
			FileOutputStream fos = new FileOutputStream(filePath);
			OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
			CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader(header);
			CSVPrinter csvPrinter = new CSVPrinter(osw, csvFormat);
			//跟上面两行代码是一样的
			//CSVPrinter csvPrinter = CSVFormat.DEFAULT.withHeader(header).print(osw);
			for (Map<String, String> map : list) {
				csvPrinter.printRecord(map.values());
			}
			csvPrinter.flush();
			csvPrinter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 解析csv文件并转成bean
	 * 参考：https://blog.csdn.net/qq_21084687/article/details/84333188
	 * 	   ：https://www.cnblogs.com/xianshen/p/13084952.html
	 * 参考：https://blog.csdn.net/wangjun5159/article/details/51655806
	 * @param file  csv文件
	 * @param clazz 类
	 * @param <T>   泛型
	 * @return 泛型bean集合
	 */
	public static <T> List<T> getCsvData(InputStream file, Class<T> clazz) {
		InputStreamReader in;
		try {
			in = new InputStreamReader(file, StandardCharsets.UTF_8);//gbk
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
		strategy.setType(clazz);
		CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(in)
				.withSeparator(',')
				.withQuoteChar('\'')
				.withMappingStrategy(strategy).build();
		return csvToBean.parse();
	}

}
